<?php defined('SYSPATH') or die('No direct script access.');

class Model_Ticket extends ORM
{  
    protected $_reload_on_wakeup = false;
    
    const TICKETS_PER_PAGE = 10;
    
    const TYPE_EMAIL = 'email';
    const TYPE_PHONE = 'phone';
    
    const STATUS_ACTIVE  = 'active';
    const STATUS_PENDING = 'pending'; 
    const STATUS_CLOSED  = 'closed'; 
    const STATUS_SPAM    = 'spam';
    const STATUS_DELETED = 'deleted';
    
    const FILTER_UNASSIGNED = 'unassigned';
    const FILTER_MINE       = 'mine';
    const FILTER_ASSIGNED   = 'assigned';
    const FILTER_CLOSED     = 'closed';
    const FILTER_SPAM       = 'spam';
    
    public static function get_tickets_per_page()
    {
        return self::TICKETS_PER_PAGE;
    } 
    
    public static function get_available_types()
    {
        return array(self::TYPE_EMAIL, self::TYPE_PHONE);
    }
    
    public static function get_available_statuses()
    {
        return array(
            self::STATUS_ACTIVE  => 'Активный',
            self::STATUS_PENDING => 'Ожидание',
            self::STATUS_CLOSED  => 'Закрыт',
            self::STATUS_SPAM    => 'Спам',
        );
    }
    
    public static function get_available_filters()
    {
        $defualt_status = array(self::STATUS_ACTIVE, self::STATUS_PENDING);
        $user           = Model_Auth::instance()->get_user();
        $user_id = 0;
        if ($user) {
            $user_id = $user->id;    
        }
        
        return array(
            self::FILTER_UNASSIGNED => array(
                'name'    => 'Не назначены',
                'url'     => self::FILTER_UNASSIGNED,
                'filters' => array(
                    'status'    => $defualt_status,
                    'assigned'  => 0,   
                ),
            ),
            self::FILTER_MINE       => array(
                'name'    => 'Мои',
                'url'     => self::FILTER_MINE,
                'filters' => array(
                    'status'    => $defualt_status,
                    'assigned'  => $user,   
                ),
            ),
            self::FILTER_ASSIGNED   => array(
                'name'    => 'Назначены',
                'url'     => self::FILTER_ASSIGNED,
                'filters' => array(
                    'status'    => $defualt_status,
                    'assigned'  => array(
                                        array('!=', 0),
                                        array('!=', $user_id),
                    ),   
                ),
            ),
            self::FILTER_CLOSED     => array(
                'name'    => 'Закрыты',
                'url'     => self::FILTER_CLOSED,
                'filters' => array(
                    'status'    => self::STATUS_CLOSED,
                    'assigned'  => null,   
                ),
            ),
            self::FILTER_SPAM       => array(
                'name'    => 'Спам',
                'url'     => self::FILTER_SPAM,
                'filters' => array(
                    'status'    => self::STATUS_SPAM,
                    'assigned'  => null,   
                ),
            ),
        );
    }
    
    public function filter($id)
    {
        $company = ORM::factory('company')->get_current();
        if (!$company->loaded()) {
            throw new HTTP_Exception_404('Нет такой компании');   
        }
        
        if (is_array($id)) {
            foreach ($id as $column => $value)
            {
                // Passing an array of column => values
                $this->where($column, '=', $value);
            }

            $this->find();
        } else {
            // Passing the primary key
            $this->where($this->_object_name.'.'.$this->_primary_key, '=', $id)->find();
        }
        
        if (!$this->loaded()) {
            throw new HTTP_Exception_404('Запись не найдена');   
        }
        
        $mailbox = ORM::factory('mailbox', $this->mailbox_id);
        if (!$mailbox->loaded()) {
            throw new HTTP_Exception_404('Нет такого ящика');   
        }
        if ($company->id != $mailbox->company_id) {
            throw new HTTP_Exception_404('Такого тикета нет'); 
        }
        
        return $this;    
    }
    
    public function get_ticket_by_email_and_subject(Model_Mailbox $mailbox, $email, $subject)
    {
        return ORM::factory('ticket')
                ->where('mailbox_id', '=', $mailbox)
                ->where('email', '=', $email)
                ->where('subject', '=', $subject)
                ->find();    
    }
    
    public function get_tickets_by_filter(Model_Mailbox $mailbox, $filter, $page = null, $count = false, $count_total = false)
    {
        if ($filter && !array_key_exists($filter['url'], self::get_available_filters())) {
            throw new Model_Exception('Неправильный фильтр');   
        }  
        
        $tickets = $this->get_tickets($mailbox, $filter['filters']['status'], $filter['filters']['assigned'], $page, $count, $count_total);
        return $tickets; 
    }
    
    public function get_tickets(Model_Mailbox $mailbox, $status = null, $assigned = null, $page = null, $count = false, $count_total = false)
    {
        if (is_array($status)) {
            foreach ($status as $_status) {
                if ($_status && !array_key_exists($_status, self::get_available_statuses())) {
                    throw new Model_Exception('Неправильный статус');   
                }   
            }    
        } else {
            if ($status && !array_key_exists($status, self::get_available_statuses())) {
                throw new Model_Exception('Неправильный статус');   
            }
        }
        
        $query = $this->_get_tickets_query($mailbox);
        
        // если нужно только кол-во и статус не закрыт и не спам и не нужно общее кол-во, то статус - активные =)
        if ($count && $status != self::STATUS_CLOSED && $status != self::STATUS_SPAM && !$count_total) {
            $status = self::STATUS_ACTIVE;    
        }
        if ($status) {
            if (is_array($status)) {
                $query->where('status', 'IN', $status);        
            } else {
                $query->where('status', '=', $status);       
            }
        }
        
        if (is_array($assigned)) {
            foreach ($assigned as $_assigned) {
                $query->where('assigned_id', $_assigned[0], $_assigned[1]);       
            }    
        } else {
            if ($assigned === true) {
                $query->where('assigned_id', '!=', 0);    
            } else if ($assigned === 0) {
                $query->where('assigned_id', '=', 0);  
            } else if ($assigned instanceof Model_User) {
                $query->where('assigned_id', '=', $assigned->id);   
            }
        }
        
        if ($count) {
            $result = $query->count_all();
            return $result;
        }  
        
        $query->order_by('status', 'ASC');
        $query->order_by('updated', 'DESC');      
            
        if ($page) {
            $_count = self::get_tickets_per_page();
            $offset = ($page - 1) * $_count;
            $query->offset($offset)->limit($_count);    
        }
        
        $tickets = $query
                    ->find_all()
                    ->as_array();
        return $tickets;         
    }
    
    public function get_tickets_from_same_client($mailbox)
    {
        if (!$this->email) {
            return array();    
        }
        $query = $this->_get_tickets_query($mailbox); 
        $tickets = $query
                    ->where('email', '=', $this->email)
                    ->where('id', '!=', $this->id)
                    ->order_by('status', 'ASC')
                    ->order_by('updated', 'DESC')
                    ->find_all()
                    ->as_array();
        return $tickets; 
    }
    
    public function get_ticket_filter()
    {
        $filters = $this->get_available_filters();
        foreach ($filters as $filter) {
            $status   = $filter['filters']['status'];
            $assigned = $filter['filters']['assigned'];
            
            $status_match = false;
            if (is_array($status)) {
                if (in_array($this->status, $status)) {
                    $status_match = true;    
                }        
            } else {
                if ($this->status ==$status) {
                    $status_match = true;   
                }       
            } 
            
            /*echo '<pre>';
            print_r($filter);
            print_r($status_match);
            echo '<hr />';*/   
            
            $assigned_match = false;
            if ($status_match) {
                if (is_array($assigned)) {
                    // != TODO Другие
                    $assigned_match = true; 
                    foreach ($assigned as $_assigned) {
                        if ($this->assigned_id == $_assigned[1]) {
                            $assigned_match = false;
                        }       
                    }    
                } else {
                    if ($assigned === true && $this->assigned_id != 0) {
                        $assigned_match = true;    
                    } else if ($assigned === 0 && (int)$this->assigned_id === 0) {
                        $assigned_match = true;  
                    } else if ($assigned instanceof Model_User && $this->assigned_id == $assigned->id) {
                        $assigned_match = true;   
                    } else if ($assigned === null) {
                        $assigned_match = true;  
                    }
                }

                
                /*echo '<pre>';
                print_r($filter);
                print_r($assigned);
                print_r($this->assigned_id); 
                var_dump($assigned_match); 
                echo '<hr />';   
                die();  */
                
                if ($assigned_match) {
                    return $filter;   
                }    
            }
        } 
        return null;   
    }
    
    public function getAttachments()
    {
        $attachments = json_decode($this->attachments, true);
        foreach ($attachments as &$attachment) {
            //$tmp = explode("\\", $attachment['filePath']); 
            //if (count($tmp) < 2) {
                $tmp = explode("/", $attachment['filePath']);   
            //}
            $filename = $tmp[count($tmp)-1];
            $filename = '/media/uploads/attachments/'.$this->mailbox_id.'/'.$filename;
            $attachment['filename'] = $filename; 
            $attachment['filesize'] = Model_Main::filesize_format(filesize($attachment['filePath'])); 
        }
        return $attachments;         
    }
    
    protected function _get_tickets_query(Model_Mailbox $mailbox)
    {
        $company = ORM::factory('company')->get_current();
        if ($company) {
            if ($company->id != $mailbox->company_id) {
                throw new Model_Exception('Такого тикета нет'); 
            }      
        } 
        
        return ORM::factory('ticket')
                    ->where('mailbox_id', '=', $mailbox->id);
    }
    
    public function add_ticket(Model_Mailbox $mailbox, $type, $client_name, $email, $phone, $subject, $text, $status, $assigned = 0, $date = null, $attachments = array(), $start_created = false)
    {
        if (!in_array($type, self::get_available_types())) {
            throw new Model_Exception('Неправильный тип');    
        }
        if (!array_key_exists($status, self::get_available_statuses())) {
            throw new Model_Exception('Неправильный статус');   
        }
        
        $user_id = 0;
        $user = Model_Auth::instance()->get_user();
        if ($user) {
            $user_id = $user->id;   
        }
        
        $from_email = null;
        if ($mailbox) {
            $from_email = $mailbox->email;    
        }
        
        // TODO проверка на принадлежность к компании
        $assigned_id = $assigned;
        if ($assigned instanceof Model_User) {
            $assigned_id = $assigned->id;    
        }
        
        if (!$date) {
            $date = time();
        }
        
        $client_name    = Security::xss_clean($client_name);
        $email          = Security::xss_clean($email);
        $phone          = Security::xss_clean($phone);
        $subject        = Security::xss_clean($subject);
        $text           = Security::xss_clean($text);
        
        $number = DB::query(Database::SELECT, 
                        "SELECT COUNT(*) AS count
                         FROM tickets
                         WHERE mailbox_id = {$mailbox->id}")->execute()->as_array();
        $number = $number[0]['count'] + 1; 
        
        $this->mailbox_id   = $mailbox->id;
        $this->user_id      = $user_id;
        $this->assigned_id  = $assigned_id;
        $this->type         = $type;
        $this->client_name  = $client_name;
        $this->email        = $email;
        $this->phone        = $phone;
        $this->subject      = $subject;
        $this->text         = $text;
        $this->status       = $status;
        $this->number       = $number;
        $this->created      = $this->updated = $date; 
        if (count($attachments)) {
            $this->attachments = json_encode($attachments);   
        }      
        $this->save();
        
        if ($user_id && $email && $from_email && !$start_created) {
            Model_Mailer::send_mail($email, $from_email, $subject, $text, $attachments);
        }
        if (!$user_id && !$start_created) {
            $company = ORM::factory('company', $mailbox->company_id);
            $users   = ORM::factory('user')->get_users($company); 
            foreach ($users as $user) {
                if ($user->check_notifications(Model_User::NOTIFICATION_NEW_TICKET)) {
                    Model_Mailer::new_ticket_notification($this, $user, $mailbox);        
                }    
            }
            if ($mailbox->is_autoreply_enabled) {
                Model_Mailer::new_ticket_autoreply($this, $mailbox);    
            }  
        }
        
        $mailbox->update_mailbox_stat();
        
        return $this;  
    }
    
    public function edit_ticket_assigned($assigned)
    {
        // TODO проверка на принадленжание $assigned компании
        
        $assigned_id = $assigned;
        if ($assigned instanceof Model_User) {
            $assigned_id = $assigned->id;    
        }
        
        $this->assigned_id = $assigned_id;
        $this->updated     = time();
        $this->save(); 
        
        $log = ORM::factory('log')->add_log($this, 'assigned', $assigned_id);
        
        $user         = ORM::factory('user', $assigned_id);
        $current_user = Model_Auth::instance()->get_user();    
        if ($user->check_notifications(Model_User::NOTIFICATION_ASSIGNED) && $user->id != $current_user->id) {
            Model_Mailer::assigned_notification($this, $user);        
        }
        
        $mailbox = ORM::factory('mailbox', $this->mailbox_id);
        $mailbox->update_mailbox_stat();
    }
    
    public function edit_ticket_status($status)
    {
        if (!array_key_exists($status, self::get_available_statuses())) {
            throw new Model_Exception('Неправильный статус');   
        }
        
        $this->status  = $status;
        $this->updated = time();
        $this->save();
        
        $log = ORM::factory('log')->add_log($this, 'status', $status); 
        
        $mailbox = ORM::factory('mailbox', $this->mailbox_id);
        $mailbox->update_mailbox_stat();
    }
    
    public function mark_ticket_as_deleted()
    {
        $this->updated = time();
        $this->status = self::STATUS_DELETED;
        $this->save(); 
        
        $mailbox = ORM::factory('mailbox', $this->mailbox_id);
        $mailbox->update_mailbox_stat();
    }
    
    public function update_ticket_replies_count()
    {
        $this->replies_count = ORM::factory('reply')->get_replies($this, true);
        $this->save();
    }
    
    public function update_ticket_updated_time()
    {
        $this->updated = time();
        $this->save();      
    }
}